using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.LAKALA;
using Admin.NET.Application.LAKALA.Dto.Request;
using Admin.NET.Application.LAKALA.Dto.Response;
using Admin.NET.Application.Service.LKL.Dto;
using Admin.NET.Core;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;

namespace Admin.NET.Application.Service.LKL;

[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class LKLPayService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly IHttpContextAccessor _httpContextAccessor;

	private readonly SqlSugarRepository<AreaBankCode> _area;

	private readonly SqlSugarRepository<UserMerchant> _userMer;

	private readonly SqlSugarRepository<UserMerchantKT> _userMerkt;

	private readonly SqlSugarRepository<LKLDicCode> _rep;

	private readonly SqlSugarRepository<PaymentRecord> _pay;

	private readonly LKLConfigOptions _config;

	private readonly UserManager _userManager;

	public LKLPayService(IHttpContextAccessor httpContextAccessor, SqlSugarRepository<UserMerchantKT> userMerkt, SqlSugarRepository<PaymentRecord> pay, UserManager userManager, SqlSugarRepository<LKLDicCode> rep, SqlSugarRepository<AreaBankCode> area, IOptions<LKLConfigOptions> lklconfig, SqlSugarRepository<UserMerchant> userMer)
	{
		_httpContextAccessor = httpContextAccessor;
		_userManager = userManager;
		_userMer = userMer;
		_rep = rep;
		_area = area;
		_config = lklconfig.Value;
		_pay = pay;
		_userMerkt = userMerkt;
	}

	/// <summary>
	/// 查看订单详情信息
	/// </summary>
	/// <param name="lKLOrderQuary"></param>
	/// <returns></returns>
	[HttpGet("/lklpay/quaryeorder")]
	public async Task<PaymentRecord> QuaryOrder([FromQuery] LKLOrderQuary lKLOrderQuary)
	{
		PaymentRecord user = await (from u in _userMerkt.Context.Queryable<PaymentRecord>()
			where u.OutTradeNo == lKLOrderQuary.out_order_no
			select u).FirstAsync();
		Thread.Sleep(2000);
		_ = _config.LKLUrl + "/api/v3/ccss/counter/order/query";
		new LKLRequest<LKLOrderQuary>
		{
			req_data = lKLOrderQuary,
			version = "3.0"
		};
		if (user.IsPay == 1)
		{
			return user;
		}
		return user;
	}

	/// <summary>
	/// 支付订单创建
	/// </summary>
	/// <returns></returns>
	[HttpPost("/lklpay/createorder")]
	public async Task<LKLOrderOutDto> CreateOrder(LKLOrderCreatInDto editMerIn)
	{
		Room room = await (from w in _rep.Context.Queryable<Room>()
			where w.Id == editMerIn.RoomId
			select w).FirstAsync();
		if (room == null)
		{
			throw Oops.Bah("该房间不存在，无法充值缴费");
		}
		UserMerchantKT user = await (from u in _userMerkt.AsQueryable()
			where u.UserId == room.CreateUserId
			select u).FirstAsync();
		if (user == null)
		{
			throw Oops.Bah("用户信息异常请检查");
		}
		if (user.status != "OPEN")
		{
			throw Oops.Bah("当前商户未审核结束");
		}
		string url = _config.LKLUrl + "/api/v3/ccss/counter/order/special_create";
		LKLRequest<LKLCreateOrderDto> lKLRequest = new LKLRequest<LKLCreateOrderDto>
		{
			req_data = new LKLCreateOrderDto
			{
				out_order_no = GetOrderNo(),
				order_efficient_time = DateTime.Now.AddDays(3.0).ToString("yyyyMMddHHmmss"),
				support_cancel = "0",
				support_refund = "0",
				support_repeat_pay = "1",
				order_info = editMerIn.order_info,
				extend_info = editMerIn.extend_info,
				merchant_no = user.ExternalCustomerNo,
				notify_url = "https://aimeter.njsnh.com:15006/lklpay/backaddorder",
				total_amount = editMerIn.total_amount
			},
			version = "3.0"
		};
		if (_httpContextAccessor.HttpContext.Request.Host.Host.Contains("dtu.iot-yy.com"))
		{
			lKLRequest.req_data.notify_url = "https://dtu.iot-yy.com:15006/lklpay/backaddorder";
		}
		else
		{
			lKLRequest.req_data.notify_url = "https://aimeter.njsnh.com/lklpay/backaddorder";
		}
		Console.WriteLine(lKLRequest.req_data.notify_url + "拉卡拉支付");
		PaymentRecord wechatPay = new PaymentRecord
		{
			MerchantId = _config.OrgCode,
			SubMerchantId = user.MerChId,
			OutTradeNo = lKLRequest.req_data.out_order_no,
			Remark = editMerIn.extend_info,
			Amount = decimal.Parse(editMerIn.total_amount) / 100m,
			Rate = editMerIn.Rate,
			Body = editMerIn.extend_info,
			IsPay = 0,
			PaymentName = editMerIn.order_info,
			Subject = editMerIn.order_info,
			PayType = PayTypeEnum.拉卡拉,
			BeforeAmount = room.Balance,
			BuildingId = room.BuildingId,
			OwnerId = room.OwnerId,
			ReceiptAmount = decimal.Parse(editMerIn.total_amount) / 100m,
			RoomId = room.Id,
			CreateTime = DateTime.Now,
			CreateUserName = _userManager.RealName
		};
		LKLResponseDto<LKLOrderOutDto> result = await LKLUtil.LKLClientRequest<LKLResponseDto<LKLOrderOutDto>>(url, JsonConvert.SerializeObject(lKLRequest));
		if (result.code == "000000")
		{
			wechatPay.TradeNo = result.resp_data.pay_order_no;
			wechatPay.ChannelId = result.resp_data.channel_id;
			_userMer.Context.Updateable<UserMerchant>(user).UpdateColumns((UserMerchant u) => u.State).ExecuteCommand();
			await _pay.InsertAsync(wechatPay);
			return result.resp_data;
		}
		return result.resp_data;
	}

	/// <summary>
	/// 查询商户进件信息状态
	/// </summary>
	/// <returns></returns>
	[HttpPost("/lklpay/quarystate")]
	public async Task<string> QuaryState(long UserId)
	{
		UserMerchant user = await (from u in _userMer.AsQueryable()
			where u.UserId == UserId
			select u).FirstAsync();
		if (user == null)
		{
			throw Oops.Bah("用户信息异常请检查");
		}
		string url = _config.LKLUrl + "/sit/api/v2/mms/openApi/queryContract";
		LKLRequest<LKLManagerQueryDto> lKLRequest = new LKLRequest<LKLManagerQueryDto>
		{
			reqData = new LKLManagerQueryDto
			{
				orderNo = GetOrderNo(),
				version = "1.0",
				contractId = "82230104900001H",
				orgCode = "1"
			}
		};
		LKLResponseDto<LKLQueryManagerOutDto> result = await LKLUtil.LKLClientRequest<LKLResponseDto<LKLQueryManagerOutDto>>(url, JsonConvert.SerializeObject(lKLRequest));
		if (result.retCode == "000000")
		{
			user.State = 0;
			_userMer.Context.Updateable(user).UpdateColumns((UserMerchant u) => u.State).ExecuteCommand();
			return "提交成功";
		}
		return result.retMsg;
	}

	/// <summary>
	/// 商户结算信息修改
	/// </summary>
	/// <returns></returns>
	[HttpPost("/lklpay/editseet")]
	public async Task<string> EditManagerPay(LKLEditSeetInDto editMerIn)
	{
		UserMerchant user = await (from u in _userMer.AsQueryable()
			where u.UserId == editMerIn.UserId
			select u).FirstAsync();
		if (user == null)
		{
			throw Oops.Bah("用户信息异常请检查");
		}
		string url = _config.LKLUrl + "/sit/api/v2/mms/openApi/changeSett";
		LKLRequest<LKLChangeSeetCardDto> lKLRequest = new LKLRequest<LKLChangeSeetCardDto>
		{
			reqData = new LKLChangeSeetCardDto
			{
				orderNo = GetOrderNo(),
				orgCode = _config.OrgCode,
				version = "1.0",
				merInnerNo = user.MerInnerNo,
				retUrl = "http://2a355318s7.vicp.fun/api/NotifController1/NodifCreateManager"
			}
		};
		LKLUtil.GetResult(lKLRequest.reqData, editMerIn);
		LKLResponseDto<LKLEditManagerOutDto> result = await LKLUtil.LKLClientRequest<LKLResponseDto<LKLEditManagerOutDto>>(url, JsonConvert.SerializeObject(lKLRequest));
		if (result.retCode == "000000")
		{
			user.State = 0;
			LKLUtil.GetResult(user, editMerIn);
			_userMer.Context.Updateable(user).UpdateColumns((UserMerchant u) => u.State).ExecuteCommand();
			return "提交成功";
		}
		return result.retMsg;
	}

	/// <summary>
	/// 修改商户费率
	/// </summary>
	/// <returns></returns>
	[HttpPost("/lklpay/editfee")]
	public async Task<string> EditManagerFee(LKLEditFeeIn editMerIn)
	{
		UserMerchant user = await (from u in _userMer.AsQueryable()
			where u.UserId == editMerIn.UserId
			select u).FirstAsync();
		if (user == null)
		{
			throw Oops.Bah("用户信息异常请检查");
		}
		string url = _config.LKLUrl + "/sit/api/v2/mms/openApi/changeFee";
		LKLRequest<LKLEditFeeDto> lKLRequest = new LKLRequest<LKLEditFeeDto>
		{
			reqData = new LKLEditFeeDto
			{
				feeData = editMerIn.Fee,
				orderNo = GetOrderNo(),
				orgCode = _config.OrgCode,
				version = "1.0",
				merInnerNo = user.MerInnerNo,
				retUrl = "http://2a355318s7.vicp.fun/api/NotifController1/NodifCreateManager"
			}
		};
		LKLResponseDto<LKLEditManagerOutDto> result = await LKLUtil.LKLClientRequest<LKLResponseDto<LKLEditManagerOutDto>>(url, JsonConvert.SerializeObject(lKLRequest));
		if (result.retCode == "000000")
		{
			user.State = 0;
			user.FeeData = editMerIn.Fee;
			_userMer.Context.Updateable(user).UpdateColumns((UserMerchant u) => new { u.State, u.FeeData }).ExecuteCommand();
			return "提交成功";
		}
		return result.retMsg;
	}

	/// <summary>
	/// 修改商户基础信息
	/// </summary>
	/// <param name="managerIn"></param>
	/// <returns></returns>
	[HttpPost("/lklpay/editmanager")]
	public async Task<string> EditManager(LKLEditMerIn managerIn)
	{
		UserMerchant user = await (from u in _userMer.AsQueryable()
			where u.UserId == managerIn.UserId
			select u).FirstAsync();
		if (user == null)
		{
			throw Oops.Bah("用户信息异常请检查");
		}
		string url = _config.LKLUrl + "/sit/api/v2/mms/openApi/changeMer";
		LKLRequest<LKLEditManagerDto> lKLRequest = new LKLRequest<LKLEditManagerDto>
		{
			reqData = new LKLEditManagerDto()
		};
		LKLEditManagerDto manager = managerIn.Adapt<LKLEditManagerDto>();
		manager.version = "1.0.0";
		manager.orderNo = GetOrderNo();
		manager.orgCode = _config.OrgCode;
		manager.merInnerNo = user.MerInnerNo;
		manager.retUrl = "http://2a355318s7.vicp.fun/api/NotifController1/NodifCreateManager";
		LKLResponseDto<LKLEditManagerOutDto> result = await LKLUtil.LKLClientRequest<LKLResponseDto<LKLEditManagerOutDto>>(url, JsonConvert.SerializeObject(lKLRequest));
		if (result.retCode == "000000")
		{
			LKLUtil.GetResult(user, managerIn);
			user.State = 0;
			_userMer.Context.Updateable(user).ExecuteCommand();
			return "提交成功";
		}
		return result.retMsg;
	}

	/// <summary>
	/// 拉卡拉商户进件
	/// </summary>
	/// <param name="managerIn"></param>
	/// <returns></returns>
	[HttpPost("/lklpay/addmanager")]
	public async Task<string> AddManager(AddManagerIn managerIn)
	{
		string url = _config.LKLUrl + "/sit/api/v2/mms/openApi/addMer";
		LKLRequest<LKLManager> lKLResponse = new LKLRequest<LKLManager>();
		LKLManager manager = managerIn.Adapt<LKLManager>();
		manager.version = "1.0.0";
		manager.orderNo = GetOrderNo();
		manager.posType = "SUPER_POS";
		manager.orgCode = _config.OrgCode;
		manager.retUrl = "http://2a355318s7.vicp.fun/api/NotifController1/NodifCreateManager";
		lKLResponse.reqData = manager;
		LKLResponseDto<LKLAddManagerDto> result = await LKLUtil.LKLClientRequest<LKLResponseDto<LKLAddManagerDto>>(url, JsonConvert.SerializeObject(lKLResponse));
		if (result.retCode == "000000")
		{
			UserMerchant user = manager.Adapt<UserMerchant>();
			user.ContractId = result.respData.contractId;
			user.UserId = managerIn.UserId;
			await _userMer.InsertAsync(user);
			return "提交成功";
		}
		return result.retMsg;
	}

	private string GetOrderNo()
	{
		Random rand = new Random();
		return DateTime.Now.ToString("yyyyMMddHHmmss").ToString() + rand.Next(10000000, 99999999);
	}

	/// <summary>
	/// 银行卡信息查询 
	/// </summary>
	/// <param name="bankno">银行卡号</param>
	/// <returns></returns>
	[HttpGet("/lklpay/bankbin")]
	public async Task<LKLBankBinDto> Getbankbin(string bankno)
	{
		string url = _config.LKLUrl + "/api/v2/mms/openApi/cardBin";
		LKLRequest<LKLCardBinDto> lKLResponse = new LKLRequest<LKLCardBinDto>
		{
			reqData = new LKLCardBinDto
			{
				orderNo = GetOrderNo(),
				cardNo = bankno,
				orgCode = _config.OrgCode,
				version = "1.0"
			}
		};
		LKLResponseDto<LKLBankBinDto> result = await LKLUtil.LKLClientRequest<LKLResponseDto<LKLBankBinDto>>(url, JsonConvert.SerializeObject(lKLResponse));
		if (result.retCode != "000000")
		{
			throw Oops.Bah(result.retMsg);
		}
		return result.respData;
	}

	/// <summary>
	/// 获取mcc数据
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpGet("/lklpay/getmcc")]
	public async Task<List<MCCOutDto>> GetMCC()
	{
		List<LKLDicCode> query = await (from u in _rep.AsQueryable()
			where u.KindCode == 0
			select u).ToListAsync();
		return (from u in query
			group u by u.TypeCode into u
			select new MCCOutDto
			{
				TypeKindName = u.Key,
				Children = (from s in query
					where s.TypeCode == u.Key
					select new MCCItemOutDto
					{
						Code = s.Code,
						CodeName = s.CodeName
					}).ToList()
			}).ToList();
	}

	/// <summary>
	/// 获取经营内容字典
	/// </summary>
	/// <returns></returns>
	[HttpGet("/lklpay/operate")]
	public async Task<List<MCCItemOutDto>> GetOperate()
	{
		return await (from u in _rep.AsQueryable()
			where u.KindCode == 1
			select new MCCItemOutDto
			{
				Code = u.Code,
				CodeName = u.CodeName
			}).ToListAsync();
	}

	/// <summary>
	/// 地区编码表
	/// </summary>
	/// <returns></returns>
	[HttpGet("/lklpay/areacode")]
	public async Task<List<AreaBankOutDto>> Getarea()
	{
		List<AreaBankCode> query = await _area.AsQueryable().ToListAsync();
		List<AreaBankCode> list = query.Where((AreaBankCode u) => u.PBankId == "-1").ToList();
		List<AreaBankOutDto> result = new List<AreaBankOutDto>();
		foreach (AreaBankCode item in list)
		{
			AreaBankOutDto children = new AreaBankOutDto
			{
				AreaCode = item.AreaCode,
				BankId = item.BankId,
				Children = new List<AreaBankOutDto>(),
				CodeName = item.CodeName,
				Name = item.Name,
				PBankId = item.PBankId
			};
			if (query.Any((AreaBankCode u) => u.PBankId == item.BankId))
			{
				GetAreaBank(query, children, item.BankId);
			}
			result.Add(children);
		}
		return result;
	}

	/// <summary>
	/// 递归获取
	/// </summary>
	/// <param name="dtos"></param>
	/// <param name="outdtos"></param>
	/// <param name="pid"></param>
	private void GetAreaBank(List<AreaBankCode> dtos, AreaBankOutDto outdtos, string pid)
	{
		List<AreaBankCode> resultDto = dtos.Where((AreaBankCode u) => u.PBankId == pid).ToList();
		if (resultDto.Count <= 0)
		{
			return;
		}
		foreach (AreaBankCode b in resultDto)
		{
			AreaBankOutDto children = new AreaBankOutDto
			{
				AreaCode = b.AreaCode,
				BankId = b.BankId,
				Children = new List<AreaBankOutDto>(),
				CodeName = b.CodeName,
				Name = b.Name,
				PBankId = b.PBankId
			};
			if (dtos.Any((AreaBankCode u) => u.PBankId == b.BankId))
			{
				GetAreaBank(dtos, children, b.BankId);
			}
			outdtos.Children.Add(children);
		}
	}
}
